package com.sailing.xjpb.common;

import com.sailing.xjpb.common.exception.ConvertException;
import com.sailing.xjpb.common.time.DateTimeFormatterUtil;
import org.springframework.util.NumberUtils;

import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Date;

/**
 * 各种类型数据转换工具
 *
 * @author YW
 */
public class TypeUtils {

    private TypeUtils() {

    }

    /**
     * 对象转换为日期对象
     * </p> 本方法可能没有对所有的日期类型考虑到位，后续如果有解析不出来的日期，需要修改本方法
     * </p> 本方法是从阿里json--TypeUtils里面摘出来进行改造的
     *
     * @param value 日期对象
     * @return 将字符串解析为日期
     */
    public static Date toDate(Object value) {
        if (value == null) {
            return null;
        }
        if (value instanceof Date) {
            return (Date) value;
        }
        if (value instanceof Calendar) {
            return ((Calendar) value).getTime();
        }
        if (value instanceof BigDecimal) {
            long longValue = longValue((BigDecimal) value);
            return new Date(longValue);
        }
        if (value instanceof Number) {
            long longValue = ((Number) value).longValue();
            return new Date(longValue);
        }
        if (value instanceof String) {
            return DateTimeFormatterUtil.smartParseToDate((String) value);
        }
        throw new ConvertException("can not cast to Date, value : " + value);
    }

    public static long longValue(BigDecimal decimal) {
        if (decimal == null) {
            return 0L;
        } else {
            int scale = decimal.scale();
            return scale >= -100 && scale <= 100 ? decimal.longValue() : decimal.longValueExact();
        }
    }

    /**
     * 对象转Number：null和""都将被转换为null
     *
     * @param val    待转换对象
     * @param tClass 转换目标类型
     * @param <T>    对象类型
     * @return 转换后的数字类型对象
     */
    public static <T extends Number> T toNumber(Object val, Class<T> tClass) {
        if (val == null) {
            return null;
        }
        String numberStr = String.valueOf(val);
        if (numberStr.isEmpty()) {
            return null;
        }
        return NumberUtils.parseNumber(numberStr, tClass);
    }
}
